package com.letoken.platform.admin.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.letoken.platform.admin.service.AdminMenuService;
import com.letoken.platform.admin.service.AdminRoleMenuService;
import com.letoken.platform.pub.constant.AdminMenuConstant;
import com.letoken.platform.pub.enums.ApiResponseEnum;
import com.letoken.platform.pub.enums.LetokenApiResponseEnum;
import com.letoken.platform.pub.exception.ApiServiceException;
import com.letoken.platform.pub.req.PageData;
import com.letoken.platform.pub.util.BeanUtil;
import com.letoken.platform.repo.admin.dao.AdminMenuMapper;
import com.letoken.platform.repo.admin.dao.AdminRoleMapper;
import com.letoken.platform.repo.admin.dao.AdminRoleMenuMapper;
import com.letoken.platform.repo.admin.dao.AdminUserRoleMapper;
import com.letoken.platform.repo.admin.manager.AdminUserManager;
import com.letoken.platform.repo.admin.po.AdminMenu;
import com.letoken.platform.repo.admin.po.AdminRole;
import com.letoken.platform.repo.admin.po.AdminRoleMenu;
import com.letoken.platform.repo.admin.po.AdminUser;
import com.letoken.platform.repo.admin.redis.AdminUserInfoRedis;
import com.letoken.platform.repo.admin.req.menu.*;
import com.letoken.platform.repo.admin.res.menu.*;
import com.letoken.platform.repo.admin.res.system.QueryAdminMenuTreeRes;
import com.letoken.platform.repo.admin.res.user.AdminUserInfoRes;
import com.letoken.platform.repo.admin.res.user.AdminUserRoleInfoRes;
import com.letoken.platform.repo.admin.util.MenuTreeUtil;
import com.letoken.platform.repo.app.manager.AdminMenuManager;
import com.letoken.platform.repo.app.manager.AdminRoleMenuManager;
import com.letoken.platform.repo.app.redis.AppLoginTokenRedis;
import com.letoken.platform.repo.utlis.PageDataUtil;
import com.letoken.platform.repo.utlis.WebUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author wyl
 * @Description 菜单Service
 * @date 2022/12/14 11:58
 * @Version 1.0
 */
@Service
@Slf4j
public class AdminMenuServiceImpl extends ServiceImpl<AdminMenuMapper, AdminMenu> implements AdminMenuService {


    @Autowired
    private AdminMenuMapper adminMenuMapper;

    @Autowired
    private AdminMenuManager admninMenuManager;

    @Autowired
    private AdminRoleMenuMapper adminRoleMenuMapper;

    @Autowired
    private AdminUserRoleMapper userRoleMapper;
    @Autowired
    private AdminRoleMapper roleMapper;

    @Autowired
    private AdminUserManager adminUserManager;

    @Autowired
    private AdminRoleMenuService adminRoleMenuService;

    @Autowired
    private AdminUserServiceImpl userService;

    @Autowired
    private AdminRoleMenuManager adminRoleMenuManager;

    /**
     * 查询菜单列表
     *
     * @param req req
     * @return re
     */
    @Override
    public PageData<QueryAdminMenuRes> queryAdminMenuList(QueryAdminMenuReq req) {
        Page<QueryAdminMenuRes> page = new Page<>(req.getPageReq().getPage(), req.getPageReq().getSize());
        Page<QueryAdminMenuRes> res = adminMenuMapper.queryAdminMenuList(page, req);
        return PageDataUtil.getPageData(res);
    }

    /**
     * 根据id查询菜单
     *
     * @param adminMenuId adminMenuId
     * @return re
     */
    @Override
    public QueryAdminMenuByIdRes queryAdminMenuById(Integer adminMenuId) {
        LambdaQueryWrapper<AdminMenu> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.select(AdminMenu::getName, AdminMenu::getDescription,AdminMenu::getUri).eq(AdminMenu::getAdminMenuId, adminMenuId);
        AdminMenu adminMenu = adminMenuMapper.selectOne(queryWrapper);
        QueryAdminMenuByIdRes res = new QueryAdminMenuByIdRes();
        res.setAdminMenuId(adminMenuId);
        res.setName(adminMenu.getName());
        res.setDescription(adminMenu.getDescription());
        res.setUri(adminMenu.getUri());
        return res;
    }


    /**
     * 新增菜单
     *
     * @param req req
     */
    @Override
    public void addAdminMenu(AddAdminMenuReq req) {
        AdminMenu adminMenu = new AdminMenu();
        BeanUtil.quickCopy(req, adminMenu);
        adminMenu.setPid(AdminMenuConstant.ONE_MENU_PID);
        adminMenu.setType(AdminMenuConstant.ONE_MENU_TYPE);
       // adminMenu.setLevel(AdminMenuConstant.ONE_MENU_LEVEL);
        adminMenu.setSort(1);
        adminMenu.setCreateTime(LocalDateTime.now());
        adminMenu.setUpdateTime(adminMenu.getCreateTime());
        int insert = adminMenuMapper.insert(adminMenu);
        if (insert == 1){
            AdminRoleMenu adminRoleMenu = new AdminRoleMenu();
            adminRoleMenu.setAdminRoleId(1);
            adminRoleMenu.setAdminMenuId(adminMenu.getAdminMenuId());
            adminRoleMenu.setCreateTime(LocalDateTime.now());
            adminRoleMenu.setUpdateTime(LocalDateTime.now());
            adminRoleMenuMapper.insert(adminRoleMenu);
        }


    }

    /**
     * 修改菜单
     *
     * @param req req
     */
    @Override
    public void updateAdminMenu(UpdateAdminMenuReq req) {
        AdminMenu adminMenu = new AdminMenu();
        BeanUtil.quickCopy(req, adminMenu);
        adminMenu.setUpdateTime(LocalDateTime.now());
        adminMenuMapper.updateById(adminMenu);
    }

    /**
     * 删除菜单
     *
     * @param adminMenuId 菜单id
     */
    @Override
    public void deleteAdminMenu(Integer adminMenuId) {
        this.deleteMenuByPid(adminMenuId, null);
        adminMenuMapper.deleteById(adminMenuId);
    }


    /**
     * 资源列表
     *
     * @param req
     * @return
     */
    @Override
    public PageData<QueryResourcesRes> queryResourcesList(QueryResourcesReq req) {
        Page<QueryResourcesRes> page = new Page<>(req.getPageReq().getPage(), req.getPageReq().getSize());
        Page<QueryResourcesRes> res = adminMenuMapper.queryResourcesList(page, req);
        return PageDataUtil.getPageData(res);
    }

    /**
     * 根据id查询资源
     *
     * @param adminMenuId
     * @return
     */
    @Override
    public QueryResourcesByIdRes queryResourcesById(Integer adminMenuId) {
        return adminMenuMapper.queryResourcesById(adminMenuId);
    }

    /**
     * 新增资源
     *
     * @param req
     * @return
     */
    @Override
    public void addResources(AddResourcesReq req) {
        AdminMenu adminMenu = new AdminMenu();
        BeanUtil.quickCopy(req, adminMenu);
        adminMenu.setType(AdminMenuConstant.ONE_MENU_TYPE);
        //adminMenu.setLevel(AdminMenuConstant.TWO_MENU_TYPE);
        adminMenu.setSort(2);
        adminMenu.setCreateTime(LocalDateTime.now());
        adminMenu.setUpdateTime(adminMenu.getCreateTime());
        int insert = adminMenuMapper.insert(adminMenu);
        if (insert == 1){
            AdminRoleMenu adminRoleMenu = new AdminRoleMenu();
            adminRoleMenu.setAdminRoleId(1);
            adminRoleMenu.setAdminMenuId(adminMenu.getAdminMenuId());
            adminRoleMenu.setCreateTime(LocalDateTime.now());
            adminRoleMenu.setUpdateTime(LocalDateTime.now());
            adminRoleMenuMapper.insert(adminRoleMenu);
       }
    }


    /**
     * 修改资源
     *
     * @param req
     * @return
     */
    @Override
    public void updateResources(UpdateResourcesReq req) {
        AdminMenu adminMenu = new AdminMenu();
        BeanUtil.quickCopy(req, adminMenu);
        adminMenu.setUpdateTime(LocalDateTime.now());
        adminMenuMapper.updateById(adminMenu);
    }

    /**
     * 根据id逻辑删除资源
     *
     * @param adminMenuId
     * @return
     */
    @Override
    public void deleteResourcesById(Integer adminMenuId) {
        this.deleteAdminMenu(adminMenuId);

    }

    /**
     * 查询一级菜单列表
     *
     * @return
     */
    @Override
    public List<QueryOneLevelRes> queryOneLevelList() {
        return adminMenuMapper.queryOneLevelList();
    }

    /**
     * 根据角色id查询所有权限
     *
     * @return
     */
    @Override
    public List<QueryAdminMenuTreeRes> queryPermissionById(Integer adminRoleId) {
        List<QueryAdminMenuTreeRes> userMenuList = adminRoleMenuMapper.selectMenuListByRole(adminRoleId);
        List<QueryAdminMenuTreeRes> treeList = MenuTreeUtil.buildMenuTree(userMenuList);
        return treeList;
    }

    /**
     * 设置角色权限
     *
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updatePermission(UpdatePermissionReq req) {
        Integer adminRoleId = req.getAdminRoleId();
        AdminRole adminRole = roleMapper.selectById(adminRoleId);
        if (adminRole == null) {
            throw new ApiServiceException(LetokenApiResponseEnum.ERROR_ADMIN_USER_031);
        }
        List<Integer> adminMenuIdList = req.getAdminMenuIdList();
        List<Integer> menuPidList = adminMenuMapper.selectIdByPidList(adminMenuIdList);
        List<Integer> menuIdList = adminMenuMapper.selectPidByIdList(adminMenuIdList);
        adminMenuIdList.addAll(menuPidList);
        adminMenuIdList.addAll(menuIdList);
        adminMenuIdList = adminMenuIdList.stream().distinct().collect(Collectors.toList());
        //删除改角色所有权限
        adminMenuMapper.deletePermissionById(adminRoleId);
        if (CollUtil.isEmpty(adminMenuIdList)) {
            throw new ApiServiceException(LetokenApiResponseEnum.ERROR_ADMIN_MENU_001);
        }
        List<AdminRoleMenu> roleMenuList = new ArrayList<>(adminMenuIdList.size());
        for (Integer adminMenuId : adminMenuIdList) {
            AdminRoleMenu adminRoleMenu = new AdminRoleMenu();
            adminRoleMenu.setAdminRoleId(adminRoleId);
            adminRoleMenu.setAdminMenuId(adminMenuId);
            adminRoleMenu.setCreateTime(LocalDateTime.now());
            adminRoleMenu.setUpdateTime(adminRoleMenu.getCreateTime());
            roleMenuList.add(adminRoleMenu);
        }
        boolean flag = adminRoleMenuService.saveBatch(roleMenuList);
        if (!flag) {
            throw new ApiServiceException(LetokenApiResponseEnum.ERROR_ADMIN_MENU_001);
        }
        List<AdminUser> adminUserList = adminUserManager.queryUserListByRoleId(adminRoleId);
        if (CollUtil.isNotEmpty(adminUserList)){
            List<QueryAdminMenuTreeRes> userMenuList = adminRoleMenuMapper.selectMenuListByRole(adminRoleId);
            List<QueryAdminMenuTreeRes> treeList = MenuTreeUtil.buildMenuTree(userMenuList);
            List<String> menuUriList = adminRoleMenuMapper.selectMenuListByAdminUserRoleId(adminRoleId);
            for (AdminUser adminUser : adminUserList) {
                AdminUserInfoRes adminUserInfo = AdminUserInfoRedis.me().getAdminUserInfo(adminUser.getToken());
                if (adminUserInfo == null){
                    adminUserInfo = new AdminUserInfoRes();
                    BeanUtil.quickCopy(adminUser, adminUserInfo);
                    AdminUserRoleInfoRes roleInfo = new AdminUserRoleInfoRes();
                    BeanUtil.quickCopy(roleInfo,adminRole);
                    adminUserInfo.setRoleInfo(roleInfo);
                }
                adminUserInfo.setMenuUriList(menuUriList);
                adminUserInfo.setTree(treeList);
                //token作为key，AdminUserInfo作为value，缓存用户信息。
                AdminUserInfoRedis.me().setObject(adminUser.getToken(), adminUserInfo);
            }
        }

    }

    @Override
    public Integer getMenuIdByUri(GetMenuIdByUriReq req) {
        return adminMenuMapper.getMenuIdByUri(req);
    }

    @Override
    public List<QueryAdminMenuTreeRes> queryByToken() {
        AdminUserInfoRes adminUserInfoRes = AppLoginTokenRedis.me().getAdminUserInfoRes();
        return adminUserInfoRes.getTree();
    }

    @Override
    public List<QueryAdminMenuTreeRes> getPermissionById(Integer adminRoleId) {
        List<QueryAdminMenuTreeRes> userMenuList = adminRoleMenuMapper.getMenuListByRole(adminRoleId);
        List<QueryAdminMenuTreeRes> treeList = MenuTreeUtil.buildMenuTree(userMenuList);
        return treeList;
    }

    @Override
    public List<QueryAdminMenuTreeRes> getPermissionList() {
        List<QueryAdminMenuTreeRes> userMenuList = adminMenuMapper.getMenuList();
        List<QueryAdminMenuTreeRes> treeList = MenuTreeUtil.buildMenuTree(userMenuList);
        return treeList;
    }

    @Override
    public List<QueryAdminMenuTreeRes> getMePermission() {
        AdminUserInfoRes adminUserInfoRes = AppLoginTokenRedis.me().getAdminUserInfoRes();
        return adminUserInfoRes.getTree();
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void modifyPermission(UpdatePermissionReq req) {
        Integer adminRoleId = req.getAdminRoleId();
        AdminRole adminRole = roleMapper.selectById(adminRoleId);
        if (adminRole == null) {
            throw new ApiServiceException(LetokenApiResponseEnum.ERROR_ADMIN_USER_031);
        }
        List<Integer> adminMenuIdList = req.getAdminMenuIdList();

        adminMenuIdList = adminMenuIdList.stream().distinct().collect(Collectors.toList());

        //删除改角色所有权限
        adminMenuMapper.deletePermissionById(adminRoleId);
        if (CollUtil.isEmpty(adminMenuIdList)) {
            throw new ApiServiceException(LetokenApiResponseEnum.ERROR_ADMIN_MENU_001);
        }
        List<AdminRoleMenu> roleMenuList = new ArrayList<>(adminMenuIdList.size());
        for (Integer adminMenuId : adminMenuIdList) {
            AdminRoleMenu adminRoleMenu = new AdminRoleMenu();
            adminRoleMenu.setAdminRoleId(adminRoleId);
            adminRoleMenu.setAdminMenuId(adminMenuId);
            adminRoleMenu.setCreateTime(LocalDateTime.now());
            adminRoleMenu.setUpdateTime(adminRoleMenu.getCreateTime());
            roleMenuList.add(adminRoleMenu);
        }
        boolean flag = adminRoleMenuService.saveBatch(roleMenuList);
        if (!flag) {
            throw new ApiServiceException(LetokenApiResponseEnum.ERROR_ADMIN_MENU_001);
        }

        List<AdminUser> adminUserList = adminUserManager.queryUserListByRoleId(adminRoleId);
        if (CollUtil.isNotEmpty(adminUserList)){
            List<QueryAdminMenuTreeRes> userMenuList = adminRoleMenuMapper.getMenuListByRole(adminRoleId);
            List<QueryAdminMenuTreeRes> treeList = MenuTreeUtil.buildMenuTree(userMenuList);
            List<String> menuUriList = adminRoleMenuMapper.getMenuListByAdminUserRoleId(adminRoleId);
            for (AdminUser adminUser : adminUserList) {
                AdminUserInfoRes adminUserInfo = AdminUserInfoRedis.me().getAdminUserInfo(adminUser.getToken());
                if (adminUserInfo == null){
                    adminUserInfo = new AdminUserInfoRes();
                    BeanUtil.quickCopy(adminUser, adminUserInfo);
                    AdminUserRoleInfoRes roleInfo = new AdminUserRoleInfoRes();
                    BeanUtil.quickCopy(roleInfo,adminRole);
                    adminUserInfo.setRoleInfo(roleInfo);
                }
                adminUserInfo.setMenuUriList(menuUriList);
                adminUserInfo.setTree(treeList);
                //token作为key，AdminUserInfo作为value，缓存用户信息。
                AdminUserInfoRedis.me().setObject(adminUser.getToken(), adminUserInfo);
            }
        }
    }

    @Override
    public List<QueryOneLevelRes> queryTwoLevelList(Integer pId) {
        return adminMenuMapper.queryTwoLevelList(pId);
    }



    /**
     * 根据父id逻辑删除权限
     */
    private void deleteMenuByPid(Integer pid, List<Integer> pidList) {
        if (pid != null) {
            List<Integer> pIds = new ArrayList<>(1);
            pIds.add(pid);
            List<Integer> ids = admninMenuManager.deleteMenuByPidList(pIds);
            if (CollUtil.isNotEmpty(ids)) {
                admninMenuManager.deleteMenuByPidList(ids);
            }
            adminRoleMenuManager.delByMenuId(pIds);
        } else if (CollUtil.isNotEmpty(pidList)) {
            admninMenuManager.deleteMenuByPidList(pidList);
        } else {
            throw new ApiServiceException("父id为空！");
        }
    }

    @Override
    public PageData<QueryPageRes> queryPageList(QueryPageReq req) {
        Page<QueryPageRes> page = new Page<>(req.getPageReq().getPage(), req.getPageReq().getSize());
        Page<QueryPageRes> res = adminMenuMapper.queryPageList(page, req);
        return PageDataUtil.getPageData(res);
    }

    @Override
    public QueryPageByIdRes queryPageById(Integer adminMenuId) {
        return adminMenuMapper.queryPageById(adminMenuId);
    }

    @Override
    public void addPage(AddPageReq req) {
        AdminMenu adminMenu = new AdminMenu();
        BeanUtil.quickCopy(req, adminMenu);
        adminMenu.setType(AdminMenuConstant.ONE_MENU_TYPE);
        adminMenu.setLevel(AdminMenuConstant.TWO_MENU_TYPE);
        adminMenu.setSort(2);
        adminMenu.setCreateTime(LocalDateTime.now());
        adminMenu.setUpdateTime(adminMenu.getCreateTime());
        int insert = adminMenuMapper.insert(adminMenu);
        if (insert == 1){
            AdminRoleMenu adminRoleMenu = new AdminRoleMenu();
            adminRoleMenu.setAdminRoleId(1);
            adminRoleMenu.setAdminMenuId(adminMenu.getAdminMenuId());
            adminRoleMenu.setCreateTime(LocalDateTime.now());
            adminRoleMenu.setUpdateTime(LocalDateTime.now());
            adminRoleMenuMapper.insert(adminRoleMenu);
        }
    }

    @Override
    public void updatePage(UpdatePageReq req) {
        AdminMenu adminMenu = new AdminMenu();
        BeanUtil.quickCopy(req, adminMenu);
        adminMenu.setUpdateTime(LocalDateTime.now());
        adminMenuMapper.updateById(adminMenu);
    }


    @Override
    public void deletePageById(Integer adminMenuId) {
        adminMenuMapper.deletePermissionById(adminMenuId);

    }

    @Override
    public void allPermission() {
        //1.删除改角色所有权限
        adminMenuMapper.deletePermissionById(1);
        //2.设置权限
        List<Integer> adminMenuIdList  = adminMenuMapper.queryAllList();
        List<AdminRoleMenu> roleMenuList = new ArrayList<>(adminMenuIdList.size());
        for (Integer adminMenuId : adminMenuIdList) {
            AdminRoleMenu adminRoleMenu = new AdminRoleMenu();
            adminRoleMenu.setAdminRoleId(1);
            adminRoleMenu.setAdminMenuId(adminMenuId);
            adminRoleMenu.setCreateTime(LocalDateTime.now());
            adminRoleMenu.setUpdateTime(adminRoleMenu.getCreateTime());
            roleMenuList.add(adminRoleMenu);
        }
        boolean flag = adminRoleMenuService.saveBatch(roleMenuList);
        if (!flag) {
            throw new ApiServiceException(LetokenApiResponseEnum.ERROR_ADMIN_MENU_001);
        }

    }

    @Override
    public List<QueryAdminMenuTreeRes> getMenuList() {
        return adminMenuMapper.getMenuList();
    }
}
